﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Objects;
using System.Text.RegularExpressions;

namespace RememberLib
{
    public class VoicePart
    {
        public string  FilePath { get; set;}
        public string FileMark { get; set; }
        public bool  IsPart { get; set;}
        public TimeSpan PartStart { get; set;}
        public TimeSpan PartEnd { get; set; }
    }

    public class PlayFlow
    {
        public string FlowName { get; set; }
        public string FlowMark { get; set; }
    }

    public class Player
    {
        RememberEntities database = new RememberEntities();
        static Player _Player = null;
        public static Player Instance(string loginID, int bookID)
        {
            if (_Player == null)
            {
                _Player = new Player(loginID, bookID);
            }
            else
            {
                _Player.LoginID = loginID;
                _Player.BookID = bookID;
            }

            return _Player;
        }

        public static TimeSpan ParseTimeSpan(string timeString)
        {
            TimeSpan ts;
            TimeSpan.TryParse(timeString, out ts);
            return ts;
        }

        public static List<PlayFlow> GetPlayFlows()
        {
            List<PlayFlow> list = new List<PlayFlow>();

            list.Add(new PlayFlow { FlowName = "Default", FlowMark = "" });
            list.Add(new PlayFlow { FlowName = "S=QADP", FlowMark = "S=QADP" });
            list.Add(new PlayFlow { FlowName = "Q=SRDA", FlowMark = "Q=SRDA" });
            list.Add(new PlayFlow { FlowName = "A=SQDP", FlowMark = "A=SQDP" });
            list.Add(new PlayFlow { FlowName = "QS=AS", FlowMark = "QS=AS" });

            return list;
        }


        public static VoicePart ParseVoicePart( string voicePartString)
        {
            //[00:08.00][00:08.00][B]
            //[00:08.00][00:08.00][L]

            //[B] books sound path
            //[L] lesson sound path
            //[DOA] this app sound folder
            //[DOB] books sound folder []
            //[DOC] customer books sound folder
            //[NOL] name of the lesson
            //[C] customer lesson sound path
            Match m;
            Regex r =
             new Regex(@"\[(?<1>[^\]]+)\]", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline);

            int index = 0;
            string startTime = string.Empty;
            string endTime = string.Empty ;
            string pathMark = string.Empty;

            for (m = r.Match(voicePartString); m.Success; m = m.NextMatch()) 
			{
                switch (index)
                {
                    case 0:
                        startTime = m.Groups[0].Value.Trim ( new char[] {'[',']'} );
                        var arr = startTime.Split(':');
                        if (arr != null && arr.Length == 2)
                        {
                            startTime = string.Format("0:{0}", startTime);
                        }
                        break;
                    case 1:
                        endTime = m.Groups[0].Value.Trim(new char[] { '[', ']' });
                        var arr2 = endTime.Split(':');
                        if (arr2 != null && arr2.Length == 2)
                        {
                            endTime = string.Format("0:{0}", endTime);
                        }

                        break;
                    case 2:
                        pathMark = m.Groups[0].Value.Trim(new char[] { '[', ']' });
                        break;

                    default:
                        break;
                }
                index++;
			}

            switch (pathMark)
            {
                case "[L]":

                    break;
                default :
                    break;
            }

            VoicePart part = new VoicePart
            {
                FileMark = pathMark,
                PartStart = ParseTimeSpan(startTime) ,
                PartEnd = ParseTimeSpan(endTime) 
            };

            return part;
        }

        public static VoicePart ParseVoicePartLrc(string lrcLineString, string lrcLineString2)
        {
            //[al:新概念英语（二）]
            //[ar:MP3 同步字幕版（美音）]
            //[ti:In or Out?]
            //[by:更多学习内容，请到VeryCD.com]
            //[00:11.22]Why did Rex run away?
            //[00:15.52]Our dog, Rex, used to sit outside our front gate and bark.
            //[00:22.54]Every time he wanted to come into the garden he would bark until someone opened the gate.
            //[00:30.39]As the neighbours complained of the noise, my husband spent weeks training him to press his paw on the latch to let himself in.
            //[00:41.56]Rex soon became an expert at opening the gate.
            //[00:46.22]However, when I was going out shopping last week, I noticed him in the garden near the gate.
            //[00:54.81]This time he was barking so that someone would let him out!
            //[01:00.09]Since then, he has developed another bad habit.
            //[01:05.10]As soon as he opens the gate from the outside, he comes into the garden and waits until the gate shuts.
            //[01:14.07]Then he sits and barks until someone lets him out.
            //[01:18.58]After this he immediately lets himself in and begins barking again.
            //[01:26.28]Yesterday my husband removed the gate and Rex got so annoyed we have not seen him since.

            Match m;
            Regex r =
             new Regex(@"\[(?<1>[^\]]+)\]", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline);

            int index = 0;
            string startTime = string.Empty;
            string endTime = string.Empty;
            string pathMark = string.Empty;
            string text = string.Empty;

            string lrc = lrcLineString + ""+ lrcLineString2;

            for (m = r.Match(lrc); m.Success; m = m.NextMatch())
            {
                switch (index)
                {
                    case 0:
                        startTime = m.Groups[0].Value.Trim(new char[] { '[', ']' });
                        var arr = startTime.Split(':');
                        if (arr != null && arr.Length == 2)
                        {
                            startTime = string.Format("0:{0}", startTime);
                        }
                        break;
                    case 1:
                        endTime = m.Groups[0].Value.Trim(new char[] { '[', ']' });
                        var arr2 = endTime.Split(':');
                        if (arr2 != null && arr2.Length == 2)
                        {
                            endTime = string.Format("0:{0}", endTime);
                        }

                        break;
                    case 2:
                        pathMark = m.Groups[0].Value.Trim(new char[] { '[', ']' });
                        break;

                    default:
                        break;
                }
                index++;
            }

            if (!string.IsNullOrEmpty(startTime))
            {
                pathMark = lrcLineString.Substring(startTime.Length);
            }

            var tryStartTime = ParseTimeSpan(startTime);
            VoicePart part = null;
            if (tryStartTime.TotalMilliseconds > 0)
            {
                part = new VoicePart
                {
                    FileMark = pathMark,
                    PartStart = ParseTimeSpan(startTime),
                    PartEnd = ParseTimeSpan(endTime),
                };
            }

            return part;
        }


        public static string BuildVoicePart(VoicePart part)
        {
            string voicePartString = string.Format("[{0}][{1}][{2}]", part.PartStart.ToString("g"), part.PartEnd.ToString("g"), part.FileMark );
            //[00:08.00][00:08.00][B]
            //[B] books sound path
            //[L] lesson sound path
            //[DOA] this app sound folder
            //[DOB] books sound folder []
            //[DOC] customer books sound folder
            //[NOL] name of the lesson
            //[C] [DOB] lesson sound path
            return voicePartString;
        }

        public VoicePart GetVoicePartFromItem( RememberItem item)
        {
            VoicePart part = null;
            if (!string.IsNullOrEmpty(item.ItemSound))
            {
                part = Player.ParseVoicePart(item.ItemSound);
            }
            else
            {
                part = new VoicePart { FileMark = "", PartStart = new TimeSpan (), PartEnd = new TimeSpan ()  };
            }

            if (part != null)
            {
                switch (part.FileMark)
                {
                    case "B":
                        break;

                    case "L":
                    default:
                        if (item.Category != null)
                        {
                            var lesson = BookBusiness.Instance().GetCategory(item.Category.Value);

                            if (lesson != null && item.Book != null)
                            {
                                part.FilePath = Context.FilePathLesson(item.Book.Value, lesson.CategoryNumber);

                            }
                        }
                        break;
                }

            }
            return part;

        }

        public Player(string loginID, int bookID)
        {
            this.LoginID = loginID;

            this.BookID = bookID;
        }

        string _LoginID;
        public string LoginID
        {
            get
            {
                return _LoginID;
            }
            set
            {
                _LoginID = value;
            }
        }

        int _BookID;
        public int BookID
        {
            get
            {
                return _BookID;
            }
            set
            {
                _BookID = value;
            }
        }

        public ObjectSet<EZMemoToday> GetList()
        {

            ObjectSet<EZMemoToday> list = database.EZMemoToday;
            foreach (var item in list)
            { 
                
            }

            return list;
        }

        public void SaveResult(int itemID, CheckResultType result)
        {
            //int itemID = _Item
            var historyList = database.RememberHistory.Where(c => c.ItemID == itemID && c.LoginID == this.LoginID );

            RememberHistory history = null;
            if (historyList != null && historyList.Count () > 0 )
            {
                history = historyList.First();
            }
            //var history = context.RememberHistory.Where(c => c.ItemID == itemID ).First();
            if (history == null)
            {
                history = new RememberHistory { ItemID = itemID, Book = this.BookID, IsActivted = true, LoginID = this.LoginID };
            }

            //if (history.ResultA == null) history.ResultA = 0;
            //if (history.ResultB == null) history.ResultB = 0;
            //if (history.ResultC == null) history.ResultC = 0;
            //if (history.ResultD == null) history.ResultD = 0;
            //if (history.CurveIndex == null) history.CurveIndex = 0;
            if (history.StartDate == null) history.StartDate = DateTime.Now;

            switch (result)
            {
                case CheckResultType.DidnotKnow:
                    history.ResultA++;
                    history.CurveIndex++;
                    history.LastResult = -1;
                    history.LastDate = DateTime.Now;
                    break;
                case CheckResultType.Knew:
                    history.ResultC++;
                    history.CurveIndex++;

                    history.LastResult = 1;
                    history.LastDate = DateTime.Now;
                    break;
                case CheckResultType.Almost:
                default:

                    history.ResultB++;
                    break;
            }

            if (historyList != null && historyList.Count() > 0)
            { 
                
            }
            else
            {
                database.AddToRememberHistory(history);
            }
            int rc = database.SaveChanges();

        }

        public void SaveItem( RememberItem item)
        {
            if (item == null)
                return;

            //int itemID = _Item
            var list = database.RememberItem.Where(c => c.ItemID == item.ItemID );

            RememberItem ri = null;
            if (list != null && list.Count() > 0)
            {
                ri = list.First();
            }
            if (ri == null)
            {
                database.AddToRememberItem( item);
            }
            else
            {
                ri.ItemID = item.ItemID;
                ri.Category = item.Category;
                ri.Book = item.Book;
                ri.ItemAnswer = item.ItemAnswer;
                ri.ItemDesc = item.ItemDesc;
                ri.ItemStatus = item.ItemStatus;
                ri.ItemFlow = item.ItemFlow;

                ri.ItemName = item.ItemName;
                ri.ItemOrder = item.ItemOrder;
                ri.ItemPicture = item.ItemPicture;
                ri.ItemQuestion = item.ItemQuestion;
                ri.ItemRelation = item.ItemRelation;
                ri.ItemSound = item.ItemSound;
                ri.ItemSource = item.ItemSource;
                ri.ItemType = item.ItemType;
                ri.ItemVideo = item.ItemVideo;
            }
            int rc = database.SaveChanges();

        }

        List<EZMemoToday> _TodayList = new List<EZMemoToday>();
        List<RememberHistory> _HistoryList = new List<RememberHistory>();

        int _Number = 0;
        public int Number { get { return _Number; }  }

        public int NewItemMax { get; set; }

        private int _Total = 0 ;
        public int Total { get { return _Total; } }
        public int Today { get { return _TodayList.Count; } }

        public RememberItem GetNextItem()
        {
            RememberItem ri = null;
            if (_TodayList.Count > 0 && _Number < _TodayList.Count)
            {
                int id = _TodayList[_Number].ItemID;

                var l = database.RememberItem.Where(c => c.ItemID == id);
                //var l = from c in context.RememberItem 
                //where c.ItemID == id
                //            select c;

                foreach (var item in l)
                {
                    ri = item;
                }
                _Number++;
            }
            return ri;
        }

        public RememberItem GetStartItem()
        {
            return GetNextItem();
        }

        public int GetHistoryDoneByBook(int bookID)
        {
            //include inactivited
            var hisList = database.RememberHistory.Where(c => c.LoginID == LoginID && c.Book == this.BookID);
            return hisList.Count();
        }

        /// <summary>
        /// Get history from today history list
        /// </summary>
        /// <param name="itemID"></param>
        /// <returns></returns>
        public RememberHistory GetHistory( int itemID)
        {
            var hisList = _HistoryList.Where(c => c.ItemID == itemID && c.LoginID == LoginID && c.Book == this.BookID).ToList ();
            if (hisList != null && hisList.Count > 0 )
            {
                return hisList[0];
            }

            return null;
        }

        public void EstimateTodayList()
        {
            _Number = 0;
            _TodayList.Clear();
            _HistoryList.Clear();

            int Number = 0;

            var hisList = database.RememberHistory.Where ( c=> c.LoginID == LoginID && c.Book == this.BookID ) ;

            foreach ( var his in hisList )
            {
                if (his.LastResult < 0)
                {
                    _TodayList.Add(new EZMemoToday { ItemID = his.ItemID, TodayID = Number, LoginID = this.LoginID });
                    _HistoryList.Add(his);
                }
                else
                {
                    if ( his.CurveIndex > 0 )
                    {
                        int minutes = Curve.GetNextMinutes(his.CurveIndex);
                        if (his.LastDate != null )
                        {
                            //DateTime showed = DateTime.Parse(his.ShowedDate);
                            DateTime plan = his.LastDate.Value.AddMinutes(minutes);
                            if (plan <= DateTime.Now)
                            {
                                _TodayList.Add(new EZMemoToday { ItemID = his.ItemID, TodayID = Number, LoginID = this.LoginID });
                                _HistoryList.Add(his);
                            }
                        }
                        else
                        {
                            _TodayList.Add(new EZMemoToday { ItemID = his.ItemID, TodayID = Number, LoginID = this.LoginID });
                            _HistoryList.Add(his);
                        }
                    }
                }

                Number++;
            }

            //part 2. parepare to remember new word from item table.
            //ObjectSet<RememberItem> list = context.RememberItem.Where ( c=> c.;
            //var list = from ri in context.RememberItem
            //           join l in context.ItemCategoryLink on ri.ItemID equals l.ItemID 
            //           select ri;

            //var list = database.RememberItem.Where ( c=> c.Book == this.BookID ) ;

            if (NewItemMax < 1) NewItemMax = 10;

            var list = (from ri in database.RememberItem
                       where ri.Book == this.BookID 
                       where !(from rh in database.RememberHistory select rh.ItemID).Contains(ri.ItemID )
                       select ri ).OrderBy (x => x.Category ).ThenBy (x => x.ItemOrder ).Take(NewItemMax);
            

            foreach (var item in list)
            {
                _TodayList.Add(new EZMemoToday { ItemID = item.ItemID, TodayID = ++Number, LoginID = this.LoginID });
                

            }
            _Total = Number;
        }

    }
}
